﻿using SUNRPA.BROWSER.BRIDGE.domain;
using SUNRPA.BROWSER.BRIDGE.util;
using SUNRPA.CONTROLS.IMPL.domain.constant;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.IO.Pipes;
using System.Reflection;
using System.Threading.Tasks;

namespace SUNRPA.BROWSER.BRIDGE {
    /// <summary>
    /// 1、浏览器与本程序间的通信
    /// 2、改通信中间程序由浏览器插件调用，随着浏览器的启动（浏览器插件）而启动，随着浏览器的插件的卸载而关闭
    /// 3、主程序与该程序通信若不存在则证明没有安装浏览器插件或者浏览器插件没有初始化
    /// 4、信息传递顺序为主程序 -> 中间 -> 浏览器插件 ---
    ///              主程序 <- 中间 <--浏览器插件 <--
    /// 5、程序--->浏览器最大1M，浏览器---->程序最大4G
    /// 6、通信时以json格式(必须)为协议，输入输出头四个自己为信息长度消息
    /// 7、次程序启动是由浏览器插件调用的，所以当浏览器插件关闭或者是时此程序也将关闭。所以需要搞好三者通信链接的关系，程序关闭链接需要重新创建
    /// </summary>
    public class BrowserBridgeEntry {
        public static LogUtil logger = new LogUtil(typeof(BrowserBridgeEntry));
        public static void Main(string[] args) { 
            try{
                //0查看当前浏览器是否开启accessibility渲染，若没有重启浏览器
                Process[] chromes = Process.GetProcessesByName("chrome");
                Process googleProcess = null;
                foreach(Process p in chromes){
                    if(p.MainWindowHandle != null && !IntPtr.Zero.Equals(p.MainWindowHandle)) { 
                        googleProcess = p;
                    }
                }
                if(googleProcess != null) {
                    try { 
                        string commandLine = DataUtil.GetCommandLineByProcessId(googleProcess.Id.ToString());
                        if(!string.IsNullOrEmpty(commandLine) && !commandLine.Contains("force-renderer-accessibility")) { 
                            if(commandLine.StartsWith("\"")) { 
                                commandLine = commandLine.Remove(0,1);
                                commandLine = commandLine.Remove(commandLine.LastIndexOf("\""), 1);
                            }
                            googleProcess.Kill();
                            Process.Start(commandLine, "--force-renderer-accessibility");
                        }
                    }catch { 
                        logger.Info("检测chrome是否开启可访问渲染出错，跳过该步骤");
                    }
                }
                //1、初始化浏览器通信
                logger.Info("初始化浏览器通信");
                BrowserRequest browserReq = new BrowserRequest();
                browserReq.method = "INIT";
                BridgeResponse browserResp = BrowserCommUtil.WriteMsgToBrowser(browserReq);
                if(!browserResp.code.Equals(CommunicationCode.OK)){ 
                    logger.Error("浏览器通信建立失败，请重启插件", null);
                    return;
                }
                //获取目标浏览器类型
                string browserType = browserResp.result.ToString();

                //2、初始化background函数分发脚本
                logger.Info($"初始化background函数分发脚本,脚本类型为{browserType}");
                browserReq.method = "INIT_BG_DISPATCHER";
                Stream stream = null;
                switch(browserType){
                    case "chrome":
                        stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SUNRPA.BROWSER.BRIDGE.script.ChromeScriptBG.js");
                        break;
                    default:
                        break;
                }
                if(stream != null){
                    browserReq.script = DataUtil.GetTextFromStream(stream);
                }else{
                    logger.Error($"初始化background脚本失败:没有读取到浏览器类型", null);
                    return;
                }
                browserResp = BrowserCommUtil.WriteMsgToBrowser(browserReq);
                if(!browserResp.code.Equals(CommunicationCode.OK)) {
                    logger.Error($"初始化background脚本失败:{browserResp.result.ToString()}", null);
                    return;
                }

                //3、初始化content函数分发脚本
                logger.Info("初始化content函数分发脚本");
                browserReq.method = DefaultContents.INITCONSCRIPT;
                stream = null;
                switch(browserType) {
                    case "chrome":
                        stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("SUNRPA.BROWSER.BRIDGE.script.ChromeScriptCon.js");
                        break;
                    default:
                        break;
                }
                if(stream != null) {
                    string script = DataUtil.GetTextFromStream(stream);
                    browserReq.param = new Dictionary<string, object>(){ { "code", script } };
                } else {
                    logger.Error($"初始化content函数分发脚本:没有读取到浏览器类型", null);
                    return;
                }
                browserResp = BrowserCommUtil.WriteMsgToBrowser(browserReq);
                if(!browserResp.code.Equals(CommunicationCode.OK)) {
                    logger.Error($"初始化content函数分发脚本:{browserResp.result.ToString()}", null);
                    return;
                }

                //4、创建进程间的管道
                logger.Info("创建进程间的管道");
                NamedPipeServerUtil.Init(DefaultContents.NAMED_PIPE_SERVER, PipeDirection.InOut);
                Task serverTask = NamedPipeServerUtil.BeginNamedPipWorker();
                Task browserListenrTask = BrowserCommUtil.BeginListerWorker();
                //这两个线程有任何一个线程结束则代表改中间程序结束
                logger.Info("开始监听两个线程");
                Task.WaitAny(new Task[] { serverTask, browserListenrTask });
                logger.Info("监听结束");
                NamedPipeServerUtil.Dispose();
                BrowserCommUtil.Dispose();
            } catch (Exception e) { 
                logger.Error("通信程序出错，请重启插件", e);
                return;
            }
        }
    }
}
